import warnings
warnings.filterwarnings("ignore")

import nltk
import pandas as pd
import numpy as np
from gensim.utils import tokenize
import re
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report

# Logistics Regression
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import GradientBoostingClassifier
from sklearn import svm
from sklearn.naive_bayes import MultinomialNB
from sklearn.ensemble import RandomForestClassifier

# Reading the Dataset


df = pd.read_csv("Data/processed_numerical_columns.csv")
df.head(5)

# Extracting the only required columns and dropping the rest of the columns
df.columns
ndex(['Airport Name', 'Reviewer Name', 'Review Date', 'Reviewer Country',
       'Review Title', 'Review Rating', 'Review Verified Status',
       'Review Text', 'Experience At Airport', 'Date Visit',
       'Type Of Traveller', 'Queuing Times', 'Terminal Cleanliness',
       'Terminal Seating', 'Terminal Signs', 'Food Beverages',
       'Airport Shopping', 'Wifi Connectivity', 'Airport Staff',
       'Recommended'],
      dtype='object')
	  
	  df_subset = df[['Review Text', 'Queuing Times', 'Terminal Cleanliness', 'Terminal Seating', 'Terminal Signs', 
                'Food Beverages', 'Airport Shopping', 'Wifi Connectivity', 'Airport Staff', 'Recommended']]
df_subset

# Above dataset contains the label column (Recommended) and rest of the columns as features¶
# Pre-processing the features
# 1. Pre-processing Review Text Column

def _process_review(review):
    review = review.lower()
    review = list(word_tokenize(review))
    
    stop_words = set(stopwords.words('english')) 
    
    review = ' '.join([word for word in review if word not in stop_words])
    
    ## Removing Punctuation
    review = re.sub(r'[^\w\s]', '', review)
    
    review = ''.join([i for i in review if not i.isdigit()]).strip()
    return review
	
	def process_reviews(list_of_reviews):
    processed_reviews = []
    for review in list_of_reviews:
        processed_reviews.append(_process_review(review))
    return processed_reviews
	ps = PorterStemmer()
lemmatizer = WordNetLemmatizer()

def tokenization(txt):
		tokens = nltk.word_tokenize(txt)
		return tokens
	
	df_subset['processed_review_text'] = process_reviews(df_subset['Review Text'])
	df_subset["processed_review_text"] = df_subset["processed_review_text"].apply(lambda x: ' '.join([ps.stem(w) for w in tokenization(x)])
	df_subset.head(5)
	
# Applying TF-IDF on the review text column

# Create feature vectors
vectorizer = TfidfVectorizer(min_df=5,
                             max_df=0.8,
                             sublinear_tf=True,
                             use_idf=True)
train_vectors = vectorizer.fit_transform(df_subset["processed_review_text"])

data = df_subset[['Queuing Times', 'Terminal Cleanliness', 'Terminal Seating', 'Terminal Signs', 'Food Beverages', 'Airport Shopping', 'Wifi Connectivity','Airport Staff']].values
data

dataset = np.concatenate((train_vectors.toarray(), data), axis=1)
data_frame_final = pd.DataFrame(dataset)
data_frame_final.head(5)

# data training

from sklearn.model_selection import train_test_split
X_train.shape

#XGBoost
clf_xgb = GradientBoostingClassifier()
clf_xgb.fit(X_train, y_train)
y_pred = clf_xgb.predict(X_test)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))

# XGBoost results
[[8701  664]
 [ 862 2348]]
              precision    recall  f1-score   support

          no       0.91      0.93      0.92      9365
         yes       0.78      0.73      0.75      3210

    accuracy                           0.88     12575
   macro avg       0.84      0.83      0.84     12575
weighted avg       0.88      0.88      0.88     12575


#Naive Bayes
mnb = MultinomialNB(alpha=0.2)
mnb.fit(X_train, y_train)
predictions = mnb.predict(X_test)
print(confusion_matrix(y_test, predictions))
print(classification_report(y_test, predictions))

#Naive Bayes results
[[8348 1017]
 [1051 2159]]
              precision    recall  f1-score   support

          no       0.89      0.89      0.89      9365
         yes       0.68      0.67      0.68      3210

    accuracy                           0.84     12575
   macro avg       0.78      0.78      0.78     12575
weighted avg       0.83      0.84      0.84     12575

#SVM
svr_lin = svm.SVC()
svr_lin.fit(X_train, y_train)
y_svr_lin_predicted = svr_lin.predict(X_test)
print(confusion_matrix(y_test, y_svr_lin_predicted))
print(classification_report(y_test, y_svr_lin_predicted))

#SVM results
[[8622  743]
 [ 963 2247]]
              precision    recall  f1-score   support

          no       0.90      0.92      0.91      9365
         yes       0.75      0.70      0.72      3210

    accuracy                           0.86     12575
   macro avg       0.83      0.81      0.82     12575
weighted avg       0.86      0.86      0.86     12575


#LogisticRegression
lr = LogisticRegression()
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))

#LogisticRegression results
[[8704  661]
 [ 907 2303]]
              precision    recall  f1-score   support

          no       0.91      0.93      0.92      9365
         yes       0.78      0.72      0.75      3210

    accuracy                           0.88     12575
   macro avg       0.84      0.82      0.83     12575
weighted avg       0.87      0.88      0.87     12575

#RandomForest
rf = RandomForestClassifier(n_estimators=200)
rf.fit(X_train, y_train)
y_pred = rf.predict(X_test)
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))

#RandomForest results
[[8925  440]
 [1216 1994]]
              precision    recall  f1-score   support

          no       0.88      0.95      0.92      9365
         yes       0.82      0.62      0.71      3210

    accuracy                           0.87     12575
   macro avg       0.85      0.79      0.81     12575
weighted avg       0.86      0.87      0.86     12575